import $ from 'jquery'
import { gsap } from 'gsap';
import 'regenerator-runtime/runtime'
import * as THREE from "three";

/*帧序列
 * <canvas class="frameCv" data-apppath="" data-path="" data-count="300"></canvas>
* new FrameFn({el:".frameCv"});
* */
export class Frame {
  constructor(opts) {
    this.canvas = document.querySelector(opts.el);
    this.shu = window.matchMedia("(orientation: portrait)").matches;//竖屏
    this.images=new Map();
    this.imagesPath = this.canvas.getAttribute('data-path');
    this.imagesPath_app = this.canvas.getAttribute('data-apppath');
    this.frameCount = this.canvas.getAttribute('data-count');
    this.context = this.canvas.getContext('2d');
    this.pix = window.devicePixelRatio;
    this.timer = null;
    this.branch = 0;
    this.sum =0;
    this.speed = 0;
    this.num = 0;
    this.curFrame ={ current:0,prev:0 }

    // 创建离屏Canvas用于双缓冲
    this.offscreenCanvas = document.createElement('canvas');
    this.offscreenCtx = this.offscreenCanvas.getContext('2d');

    this.init();
  }
  init(){
    const that = this;
    this.setSize(this.canvas.parentElement.getBoundingClientRect().width*this.pix,this.canvas.parentElement.getBoundingClientRect().height*this.pix)
    window.addEventListener("resize", this.resize.bind(this));
    this.pathArr=[
      {url:this.imagesPath,sum:532,id:0},
    ]
    this.loadStep = 0;
    this.sendLoad(this.pathArr[0]);
  }
  setSize(width, height) {
    this.canvas.width = width;
    this.canvas.height = height;
    this.offscreenCanvas.width = width;
    this.offscreenCanvas.height = height;
    this.coverSize = this.imgCover();
  }
  sendLoad(child){
    let srcs = [];
    for (let i = 0; i < child.sum; i+=1) {
      srcs.push(child.url + i.toString().padStart(5, '0') + ".png.webp?v=1");
    }
    this.loadImagesAll(srcs,child.id);
  }
  async loadImagesAll(urls,id){
    try {
      // 并行加载所有图片
      const loadPromises = urls.map(url => this.loadImage(url));
      const frames = await Promise.all(loadPromises);
      this.images.set(id, frames);
      this.loadStep++;
      this.drawFitCoverImage(0);
    } catch (error) {
      console.error('图片加载失败:', error);
    }
  }
  async loadImage(url){
    const that = this;
    return new Promise(function (resolve, reject) {
      var img = new Image();
      img.src = url;
      if (img.complete) {
        resolve(img);
      } else {
        img.addEventListener('load', function () {
          resolve(img);
        });
        img.addEventListener('error', function () {
          resolve();
        });
      }
    });
  }
  imgCover(){
    let imgAspect = 1920 / 1080;
    if(this.shu){imgAspect = 1080/1600;}
    const targetAspect = this.canvas.width / this.canvas.height;
    let drawWidth, drawHeight, offsetX, offsetY;
    if (imgAspect > targetAspect) {
      // 图片比目标区域更宽，按高度适配
      drawHeight = this.canvas.height;
      drawWidth = drawHeight * imgAspect;
      offsetX = (this.canvas.width - drawWidth) / 2;
      offsetY = 0;
    } else {
      // 图片比目标区域更高，按宽度适配
      drawWidth = this.canvas.width;
      drawHeight = drawWidth / imgAspect;
      offsetX = 0;
      offsetY = (this.canvas.height - drawHeight) / 2;
    }
    return {x:offsetX,y:offsetY,w:drawWidth,h:drawHeight}
  }
  drawFitCoverImage(frameIndex){
    const img = this.images.get(this.branch)[frameIndex];
    if(img){
      this.offscreenCtx.clearRect(0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height);
      this.offscreenCtx.drawImage(
        img,
        0, 0, img.width, img.height,  // 源图片区域
        this.coverSize.x, this.coverSize.y, this.coverSize.w, this.coverSize.h  // 目标区域
      );
      // 2. 绘制到主Canvas
      this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
      this.context.drawImage(this.offscreenCanvas, 0, 0);
    }
  }
  createFrame(){
    const that = this;
    let fps = 3.33;
    let time = new Date().getTime();
    this.isPlay = false;
    this.render = () =>{
      if(that.isPlay&&(new Date().getTime() - time > fps)){
        that.num = that.num <= 0 ? 0 : that.num;
        that.num = that.num > (that.frameCount-1) ? (that.frameCount-1) : that.num;
        that.drawFitCoverImage(that.images[that.num]);
        time = new Date().getTime()
      }
      that.timer = requestAnimationFrame(that.render);
    };
    this.render();
  }
  resize(){
    var that = this;
    this.canvas.width = this.canvas.parentElement.getBoundingClientRect().width*this.pix;
    this.canvas.height = this.canvas.parentElement.getBoundingClientRect().height*this.pix;
    that.drawFitCoverImage(that.images[that.num]);
  }
  loading(){
    this.sum++;
    const goNum = parseInt(Math.min(this.sum,835)*100/835);
    this.goEl.innerHTML=goNum;
  }
  upData(num){
    const that = this;
    this.curFrame.current = Math.min(num,(that.frameCount-1));
    if(this.curFrame.current!==this.curFrame.prev){
      that.drawFitCoverImage(this.curFrame.current);
      this.curFrame.prev = this.curFrame.current;
    }
  }
}

export class BannerGl {
  constructor(opts) {
    const setting = {
      loop:true,
      call:function (){},
      running:function(){}
    }
    this.opt =  Object.assign(setting,opts);
    this.scene = new THREE.Scene();
    this.timer = null;
    this.vertex = `varying vec2 vUv;void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );}`;
    this.fragment = opts.fragment;
    this.uniforms = opts.uniforms;
    this.renderer = new THREE.WebGLRenderer();
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(this.width, this.height);
    this.renderer.setClearColor(0xeeeeee, 1);
    this.duration = opts.duration || 1;
    this.debug = opts.debug || false
    this.easing = opts.easing || 'easeInOut'

    this.prevClicker = document.querySelector(".bannerPrev");
    this.nextClicker = document.querySelector(".bannerNext");


    this.container = document.getElementById("bannerSlider");
    this.images = JSON.parse(this.container.getAttribute('data-images'));
    this.width = this.container.offsetWidth;
    this.height = this.container.offsetHeight;
    this.container.appendChild(this.renderer.domElement);

    this.camera = new THREE.PerspectiveCamera(
      70,
      window.innerWidth / window.innerHeight,
      0.001,
      1000
    );

    this.camera.position.set(0, 0, 2);
    this.time = 0;
    this.current = 0;
    this.textures = [];

    this.paused = true;
    this.initiate(()=>{
      this.setupResize();
      this.addObjects();
      this.resize();
      this.clickEvent();
      this.play();
    })

  }

  initiate(cb){
    const promises = [];
    let that = this;
    this.images.forEach((url,i)=>{
      let promise = new Promise(resolve => {
        that.textures[i] = new THREE.TextureLoader().load( url, resolve );
      });
      promises.push(promise);
    })

    Promise.all(promises).then(() => {
      cb();
    });
  }

  clickEvent(){
    this.nextClicker.addEventListener('click',()=>{
      this.next();
    });
    this.prevClicker.addEventListener('click',()=>{
      this.prev();
    });
  }

  setupResize() {
    window.addEventListener("resize", this.resize.bind(this));
  }

  resize() {
    this.width = this.container.offsetWidth;
    this.height = this.container.offsetHeight;
    this.renderer.setSize(this.width, this.height);
    this.camera.aspect = this.width / this.height;


    // image cover
    this.imageAspect = this.textures[0].image.height/this.textures[0].image.width;
    let a1; let a2;
    if(this.height/this.width>this.imageAspect) {
      a1 = (this.width/this.height) * this.imageAspect ;
      a2 = 1;
    } else{
      a1 = 1;
      a2 = (this.height/this.width) / this.imageAspect;
    }

    this.material.uniforms.resolution.value.x = this.width;
    this.material.uniforms.resolution.value.y = this.height;
    this.material.uniforms.resolution.value.z = a1;
    this.material.uniforms.resolution.value.w = a2;

    const dist  = this.camera.position.z;
    const height = 1;
    this.camera.fov = 2*(180/Math.PI)*Math.atan(height/(2*dist));

    this.plane.scale.x = this.camera.aspect;
    this.plane.scale.y = 1;

    this.camera.updateProjectionMatrix();


  }

  addObjects() {
    let that = this;
    this.material = new THREE.ShaderMaterial({
      extensions: {
        derivatives: "#extension GL_OES_standard_derivatives : enable"
      },
      side: THREE.DoubleSide,
      uniforms: {
        time: { type: "f", value: 0 },
        progress: { type: "f", value: 0 },
        border: { type: "f", value: 0 },
        intensity: { type: "f", value: 0 },
        scaleX: { type: "f", value: 40 },
        scaleY: { type: "f", value: 40 },
        transition: { type: "f", value: 40 },
        swipe: { type: "f", value: 0 },
        width: { type: "f", value: 0 },
        radius: { type: "f", value: 0 },
        texture1: { type: "f", value: this.textures[0] },
        texture2: { type: "f", value: this.textures[1] },
        displacement: { type: "f", value: new THREE.TextureLoader().load(this.container.dataset.disp) },
        resolution: { type: "v4", value: new THREE.Vector4() },
      },
      // wireframe: true,
      vertexShader: this.vertex,
      fragmentShader: this.fragment
    });

    this.geometry = new THREE.PlaneGeometry(1, 1, 2, 2);

    this.plane = new THREE.Mesh(this.geometry, this.material);
    this.scene.add(this.plane);
  }

  stop() {
    this.paused = true;
  }

  play() {
    this.paused = false;
    this.render();
  }
  start(){
    if(this.opt.loop){this.loop();}
  }

  next() {
    if (this.isRunning) return;
    this.isRunning = true;
    clearTimeout(this.timer);
    let len = this.textures.length;
    let nextNum = (this.current + 1)<len?(this.current + 1):0;
    let nextTexture = this.textures[nextNum];
    this.material.uniforms.texture2.value = nextTexture;
    gsap.timeline({
      onStart: ()=>{
        this.opt.call(nextNum);
      },
      onComplete: () => {
        this.current = nextNum;
        this.material.uniforms.texture1.value = nextTexture;
        this.material.uniforms.progress.value = 0;
        this.isRunning = false;
        if(this.opt.loop){
          this.loop();
        }
      }
    }).to(this.material.uniforms.progress, {
      value: 1,
      duration: 0.8
    })
  }
  prev() {
    if (this.isRunning) return;
    this.isRunning = true;
    clearTimeout(this.timer);
    let len = this.textures.length;
    let nextNum = (this.current - 1)>=0?(this.current - 1):len-1;
    let nextTexture = this.textures[nextNum];
    this.material.uniforms.texture2.value = nextTexture;
    gsap.timeline({
      onStart: ()=>{
        this.opt.call(nextNum);
      },
      onComplete: () => {
        this.current = nextNum;
        this.material.uniforms.texture1.value = nextTexture;
        this.material.uniforms.progress.value = 0;
        this.isRunning = false;
        if(this.opt.loop){
          this.loop();
        }
      }
    }).to(this.material.uniforms.progress, {
      value: 1,
      duration: 0.8
    })
  }
  render() {
    if (this.paused) return;
    this.time += 0.05;
    this.material.uniforms.time.value = this.time;
    // this.material.uniforms.progress.value = this.settings.progress;

    this.material.uniforms.intensity.value = 16;
    this.opt.running();
    // this.camera.position.z = 3;
    // this.plane.rotation.y = 0.4*Math.sin(this.time)
    // this.plane.rotation.x = 0.5*Math.sin(0.4*this.time)

    requestAnimationFrame(this.render.bind(this));
    this.renderer.render(this.scene, this.camera);
  }
  loop(){
    const that = this;
    this.timer = setTimeout(function(){
      that.next();
    },3500);
  }
}

/*普通切换轮播
container:$('#slider')
params:
  sliderPic
  sliderMsg
  sliderDot
  sliderPrev
  sliderNext
  sliderSum
 */
export class SliderMove{
  constructor(opts={}) {
    const setting = {
      container:$('#slider'),
      loop:true,
      isTouch:true,
      time:2200,
      call:function (){}
    }
    this.opts =  Object.assign(setting,opts);
    this.el = {
      bannerPic:this.opts.container.find('.sliderPic'),
      bannerMsg:this.opts.container.find('.sliderMsg'),
      bannerDot:this.opts.container.find('.sliderDot'),
      prev:this.opts.container.find('.sliderPrev'),
      next:this.opts.container.find('.sliderNext'),
      sum:this.opts.container.find('.sliderSum'),
      timer:null,
      len:0,
      cur:0,
      ani:false
    }
    this.container = this.opts.container;
    this.shu = window.matchMedia("(orientation: portrait)").matches;//竖屏
    this.tsMedia=[];
    this.el.len = this.el.bannerPic.length;
    if(this.opts.isTouch){this.touchMove(this.container);}
    const that = this;
    if(this.el.len>1){
      this.el.bannerDot.on('click',function (){
        var key = parseInt($(this).attr("data-num"));
        clearTimeout(that.el.timer);
        that.stopMedia();
        that.next(1,key);
      });
      this.el.next.on('click',function (){
        clearTimeout(that.el.timer);
        that.next(0);
      })
      this.el.prev.on('click',function (){
        clearTimeout(that.el.timer);
        that.next(-1);
      })
      this.el.bannerPic.each(function(){
        let curMedia = $(this)[0].querySelector('video');
        if(curMedia){
          curMedia.onended = function(){that.next();}
        }
      });
    }
  }
  loop(){
    const that = this;
    if(this.el.len>1){
      that.el.timer = setTimeout(function (){
        that.next();
      },3000);
    }
  }
  start(){
    const that = this;
    var curMsg = that.el.bannerMsg.eq(that.el.cur);
    var curDot = that.el.bannerDot.eq(that.el.cur);
    curMsg.addClass('on');
    curDot.addClass('on');
  }
  stop(){
    const that = this;
    clearTimeout(that.el.timer);
  }
  stopMedia(){
    const that = this;
    let curList = that.el.bannerPic.eq(that.el.cur);
    if(curList[0].querySelector('video')&&!that.shu){
      curList[0].querySelector('video').pause();
    }else if(that.shu&&curList[0].querySelector('.MediaTs')){
      that.tsMedia[that.el.cur].stop();
    }
  }
  next(type=0,n=0){
    const that = this;
    if(that.el.ani) return false;
    clearTimeout(that.el.timer);
    that.el.ani = true;
    var curList = that.el.bannerPic.eq(that.el.cur);
    var curMsg = that.el.bannerMsg.eq(that.el.cur);
    var curDot = that.el.bannerDot.eq(that.el.cur);
    if(type===0){
      that.el.cur = that.el.cur < that.el.len-1 ? that.el.cur + 1 : 0;
    }else if(type===(-1)){
      that.el.cur = that.el.cur > 0 ? that.el.cur - 1 : that.el.len-1;
    }else{
      that.el.cur = n;
    }
    var nextList = that.el.bannerPic.eq(that.el.cur);
    var nextMsg = that.el.bannerMsg.eq(that.el.cur);
    var nextDot = that.el.bannerDot.eq(that.el.cur);
    if(nextList.find('.pic').attr('data-src')){
      that.container[0].setAttribute('data-url',nextList.find('.pic').attr('data-src'));
    }
    curList.addClass('out');
    curMsg.addClass('out');
    curDot.addClass('out');
    nextList.addClass('in');
    nextMsg.addClass('in');
    nextDot.addClass('in');
    nextDot.addClass('on').siblings().removeClass('on');
    that.opts.call(that.el.cur);
    setTimeout(function(){
      nextList.addClass('on').siblings().removeClass('on');
      nextMsg.addClass('on').siblings().removeClass('on');
      curList.removeClass('out');
      curMsg.removeClass('out');
      curDot.removeClass('out');
      nextList.removeClass('in');
      nextMsg.removeClass('in');
      nextDot.removeClass('in');
      that.el.ani = false;
      if(that.opts.loop){that.loop();}
    },this.opts.time);
    that.el.sum.text("0"+(that.el.cur+1));
  }
  touchMove(elm){
    const that = this;
    var move = {};
    elm.on('touchstart',function(e){
      //获取接触屏幕时的X和Y
      move.endX = 0;
      move.endY = 0;
      move.startX = e.originalEvent.changedTouches[0].pageX;
      move.startY = e.originalEvent.changedTouches[0].pageY;
    });
    elm.on('touchmove',function(e) {
      //获取滑动屏幕时的X,Y
      move.endX = e.originalEvent.changedTouches[0].pageX;
      move.endY = e.originalEvent.changedTouches[0].pageY;
    });
    elm.on('touchend',function(e) {
      var distanceX = null;
      var distanceY = null;
      //获取滑动屏幕时的X,Y
      if(move.endX ==0 || move.endY ==0){
        distanceX = 0;
        distanceY = 0;
      }else{
        distanceX = move.endX - move.startX;
        distanceY = move.endY - move.startY;
      }
      if (Math.abs(distanceX) > Math.abs(distanceY) && distanceX > 50) {
        clearTimeout(that.el.timer);
        that.stopMedia();
        that.next(-1);
      }
      else if (Math.abs(distanceX) > Math.abs(distanceY) && distanceX < (-50)) {
        clearTimeout(that.el.timer);
        that.stopMedia();
        that.next(0);
      }
    });
  }
  creatTs(el,src,auto=false,loop=false,endFn){
    let ts = new JSMpeg.VideoElement(el,src,{
      autoplay:auto,
      loop:loop,
      control:false,
      decodeFirstFrame:false,
      chunkSize:512*512,
      hooks:{
        play:()=>{
          el.classList.add('active');
        },
      }
    },{
      audio:false,
      onEnded:()=>{
        endFn();
      },
    });
    return ts;
  }
}

export class SliderMoveHome{
  constructor(opts={}) {
    const setting = {
      container:$('#slider'),
      loop:true,
      isTouch:true,
      time:2200,
      call:function (){}
    }
    this.opts =  Object.assign(setting,opts);
    this.el = {
      bannerPic:this.opts.container.find('.sliderPic'),
      bannerMsg:this.opts.container.find('.sliderMsg'),
      bannerDot:this.opts.container.find('.sliderDot'),
      prev:this.opts.container.find('.sliderPrev'),
      next:this.opts.container.find('.sliderNext'),
      sum:this.opts.container.find('.sliderSum'),
      timer:null,
      len:0,
      cur:0,
      ani:false
    }
    this.container = this.opts.container;
    this.shu = window.matchMedia("(orientation: portrait)").matches;//竖屏
    this.tsMedia=[];
    this.el.len = this.el.bannerPic.length;
    if(this.opts.isTouch){this.touchMove(this.container);}
    const that = this;
    if(this.el.len>1){
      this.el.bannerDot.on('click',function (){
        var key = parseInt($(this).attr("data-num"));
        clearTimeout(that.el.timer);
        that.stopMedia();
        that.next(1,key);
      });
      this.el.next.on('click',function (){
        clearTimeout(that.el.timer);
        that.next(0);
      })
      this.el.prev.on('click',function (){
        clearTimeout(that.el.timer);
        that.next(-1);
      })
      this.el.bannerPic.each(function(){
        let curMedia = $(this)[0].querySelector('video');
        if(curMedia){
          curMedia.onended = function(){that.next();}
        }
      });
    }
  }
  loop(){
    const that = this;
    if(this.el.len>1){
      that.el.timer = setTimeout(function (){
        that.next();
      },3000);
    }
  }
  start(){
    const that = this;
    var curMsg = that.el.bannerMsg.eq(that.el.cur);
    var curDot = that.el.bannerDot.eq(that.el.cur);
    curMsg.addClass('on');
    curDot.addClass('on');
  }
  stop(){
    const that = this;
    clearTimeout(that.el.timer);
  }
  stopMedia(){
    const that = this;
    let curList = that.el.bannerPic.eq(that.el.cur);
    if(curList[0].querySelector('video')&&!that.shu){
      curList[0].querySelector('video').pause();
    }else if(that.shu&&curList[0].querySelector('.MediaTs')){
      that.tsMedia[that.el.cur].stop();
    }
  }
  next(type=0,n=0){
    const that = this;
    clearTimeout(that.el.timer);
    var curList = that.el.bannerPic.eq(that.el.cur);
    var curMsg = that.el.bannerMsg.eq(that.el.cur);
    var curDot = that.el.bannerDot.eq(that.el.cur);
    if(type===0){
      that.el.cur = that.el.cur < that.el.len-1 ? that.el.cur + 1 : 0;
    }else if(type===(-1)){
      that.el.cur = that.el.cur > 0 ? that.el.cur - 1 : that.el.len-1;
    }else{
      that.el.cur = n;
    }
    var nextList = that.el.bannerPic.eq(that.el.cur);
    var nextMsg = that.el.bannerMsg.eq(that.el.cur);
    var nextDot = that.el.bannerDot.eq(that.el.cur);
    nextDot.addClass('on').siblings().removeClass('on');
    nextList.addClass('on').siblings().removeClass('on');
    that.opts.call(that.el.cur);
    setTimeout(function(){
      if(that.opts.loop){that.loop();}
    },this.opts.time);
  }
  touchMove(elm){
    const that = this;
    var move = {};
    elm.on('touchstart',function(e){
      //获取接触屏幕时的X和Y
      move.endX = 0;
      move.endY = 0;
      move.startX = e.originalEvent.changedTouches[0].pageX;
      move.startY = e.originalEvent.changedTouches[0].pageY;
    });
    elm.on('touchmove',function(e) {
      //获取滑动屏幕时的X,Y
      move.endX = e.originalEvent.changedTouches[0].pageX;
      move.endY = e.originalEvent.changedTouches[0].pageY;
    });
    elm.on('touchend',function(e) {
      var distanceX = null;
      var distanceY = null;
      //获取滑动屏幕时的X,Y
      if(move.endX ==0 || move.endY ==0){
        distanceX = 0;
        distanceY = 0;
      }else{
        distanceX = move.endX - move.startX;
        distanceY = move.endY - move.startY;
      }
      if (Math.abs(distanceX) > Math.abs(distanceY) && distanceX > 50) {
        clearTimeout(that.el.timer);
        that.stopMedia();
        that.next(-1);
      }
      else if (Math.abs(distanceX) > Math.abs(distanceY) && distanceX < (-50)) {
        clearTimeout(that.el.timer);
        that.stopMedia();
        that.next(0);
      }
    });
  }
  creatTs(el,src,auto=false,loop=false,endFn){
    let ts = new JSMpeg.VideoElement(el,src,{
      autoplay:auto,
      loop:loop,
      control:false,
      decodeFirstFrame:false,
      chunkSize:512*512,
      hooks:{
        play:()=>{
          el.classList.add('active');
        },
      }
    },{
      audio:false,
      onEnded:()=>{
        endFn();
      },
    });
    return ts;
  }
}

/*
单屏滚动
new SingleScreen({
  container:document.querySelector('#fullPage'),
  beforeLeave:function(cur,curElm,next,nextElem){},
  afterLeave:function(cur,elm){}
});
*/
export class SingleScreen{
  constructor(opts) {
    const setting = {
      /*默认参数*/
      container: document.querySelector('#fullPage'),
      threshold: 800,// 触发滚动事件的阈值，越小越灵敏
      pageSpeed: .8,// 滚屏速度
      elm:".pages",
      beforeLeave:function(){},// 页面离开事件
      afterLeave:function(){},// 页面离开后事件
      call: function() {}
    }
    this.opt =  Object.assign(setting,opts);
    this.sections = this.opt.container.querySelectorAll(this.opt.elm);
    this.rect = this.opt.container.getBoundingClientRect();
    this.stepHei = [];
    this.length = this.sections.length;
    this.diff = 0;
    this.pages = {
      nowPage:0,
      deltaY:0,
      isScrolling:true,
      isNext:true,
      isPrev:true,
      translate3dY:0
    }
    this.init();
  }
  init(){
    let allHei = 0;
    for (let i = 0; i < this.length; i++) {
      this.stepHei.push(0);
    }
    gsap.set(this.opt.container,{'--current':0,height:window.innerHeight});
    this.event();
  }
  resize(){
    gsap.set(this.opt.container,{height:window.innerHeight});
  }
  scrollPage(pageIndex){
    const that = this;
    let pageDiff = pageIndex - this.pages.nowPage;
    let leaveSection = this.sections[this.pages.nowPage];
    let nowSection = this.sections[pageIndex];
    if(pageIndex>=0 && pageIndex <= this.length - 1 && pageDiff){
      this.pages.translate3dY = -that.stepHei[pageIndex];
      leaveSection.classList.remove('active');
      if (typeof that.opt.beforeLeave === 'function') {
        that.opt.beforeLeave(this.pages.nowPage,leaveSection,pageIndex,nowSection,pageDiff);
      }
      gsap.timeline({
        onStart:()=>{
          that.pages.isScrolling = true;
        },
        onComplete:()=>{
          that.pages.nowPage = pageIndex;
          that.opt.afterLeave(pageIndex);
        }
      })
        .to(this.opt.container,{'--current':pageIndex,duration:this.opt.pageSpeed,ease:"power2.inout"})
      return true;
    }else{
      that.opt.afterLeave(this.pages.nowPage);
    }
  }
  next(callback){
    if (this.scrollPage(this.pages.nowPage + 1)){
      let arg = Array.prototype.slice.call(arguments, 1)
      if (typeof callback === 'function') {callback(arg)}
      return true
    }
  }
  prev(callback){
    if (this.scrollPage(this.pages.nowPage - 1)) {
      let arg = Array.prototype.slice.call(arguments, 1)
      if (typeof callback === 'function') {
        callback(arg)
      }
      return true
    }
  }
  moveTo(pageIndex,callback){
    if (this.pages.isScrolling) {return false}
    this.pages.isScrolling = true;
    if (this.scrollPage(pageIndex)) {
      let arg = Array.prototype.slice.call(arguments, 1)
      if (typeof callback === 'function') {
        callback(arg)
      }
      return true
    }
  }
  event(){
    window.addEventListener("resize", this.resize.bind(this));
    if(window.matchMedia("(orientation: portrait)").matches){
      this.touchMove($(this.opt.container));
    }else{
      this.bindMouseWheel();
    }
  }
  touchMove(elm){
    const that = this;
    var move = {};
    let onceTouch = false;
    elm.on('touchstart',function(e){
      //获取接触屏幕时的X和Y
      onceTouch = true;
      move.endX = 0;
      move.endY = 0;
      move.startX = e.originalEvent.changedTouches[0].pageX;
      move.startY = e.originalEvent.changedTouches[0].pageY;
    });
    elm.on('touchmove',function(e) {
      //获取滑动屏幕时的X,Y
      if (that.pages.isScrolling || !onceTouch) {
        return false
      }
      move.endX = e.originalEvent.changedTouches[0].pageX;
      move.endY = e.originalEvent.changedTouches[0].pageY;
    });
    elm.on('touchend',function(e) {
      var distanceX = null;
      var distanceY = null;
      onceTouch = true;

      //获取滑动屏幕时的X,Y
      if(move.endX ==0 || move.endY ==0){
        distanceX = 0;
        distanceY = 0;
      }else{
        distanceX = move.endX - move.startX;
        distanceY = move.endY - move.startY;
      }
      if (distanceY > 70) {
        that.prev()
      }
      else if (distanceY < (-70)) {
        that.next()
      }
    });
  }
  bindMouseWheel(){
    //鼠标滚动事件
    let type
    if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1) {
      type = 'DOMMouseScroll'
    } else {
      type = 'mousewheel'
    }
    document.addEventListener(type,this.mouseWheelHandle.bind(this),false)
  }
  mouseWheelHandle(event){
    if (this.pages.isScrolling) {return false}
    this.pages.isScrolling = true;
    this.pages.deltaY = event.detail || -event.wheelDelta || event.deltaY
    if (this.pages.deltaY > 0) {
      if(!this.pages.isNext) return false;
      this.next()
      // console.log('next')
    } else if (this.pages.deltaY < 0) {
      if(!this.pages.isPrev) return false;
      this.prev()
      // console.log('pre')
    }
  }
  stop(){
    this.pages.isScrolling = true;
  }
  play(){
    this.pages.isScrolling = false;
  }
}